/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lvyh.lightframe.job.admin.service;

import com.alibaba.fastjson.JSON;
import com.lvyh.lightframe.job.admin.bean.JobUserBean;
import com.lvyh.lightframe.job.Constants;
import com.lvyh.lightframe.job.enums.ErrorCode;
import com.lvyh.lightframe.job.admin.util.CookieUtil;
import com.lvyh.lightframe.job.common.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Configuration
@ConditionalOnClass(JobMainDataService.class)
public class UserLoginService {

    @Autowired
    private JobMainDataService jobMainDataService;

    private static List<String> excludePatternList = new ArrayList<String>();

    static {
        excludePatternList.add("/monitor/fetch");
        excludePatternList.add("/monitor/heartbeat");
        excludePatternList.add("/toLogin");
        excludePatternList.add("/login");
        excludePatternList.add("/logout");
    }

    public boolean checkExcludeUrl(HttpServletRequest request) {
        String requestPath = request.getServletPath();
        if (excludePatternList.contains(requestPath)) {
            return true;
        }

        return false;
    }

    private String makeToken(JobUserBean jobUserBean) {
        String tokenJson = JSON.toJSONString(jobUserBean, true);
        String tokenHex = new BigInteger(tokenJson.getBytes()).toString(16);
        return tokenHex;
    }

    private JobUserBean getConfUserBean(String username) throws Exception {
        JobUserBean condition = new JobUserBean();
        condition.setUserName(username);
        List<JobUserBean> result = jobMainDataService.selectJobUser(condition);
        return !CollectionUtils.isEmpty(result) ? result.get(0) : null;
    }


    private JobUserBean parseUserLoginKey(String tokenHex) {
        JobUserBean jobUserBean = null;
        if (tokenHex != null) {
            String tokenJson = new String(new BigInteger(tokenHex, 16).toByteArray());
            jobUserBean = JSON.parseObject(tokenJson, JobUserBean.class);
        }
        return jobUserBean;
    }

    public Result<String> login(HttpServletResponse response, String usernameParam, String passwordParam, boolean ifRemember) throws Exception {

        JobUserBean jobUserBean = getConfUserBean(usernameParam);
        if (jobUserBean == null) {
            Result.create(ErrorCode.FAILED, "Account or password is illegal.");
        }

        String passwordParamMd5 = DigestUtils.md5DigestAsHex(passwordParam.getBytes());
        if (!jobUserBean.getPwd().equals(passwordParamMd5)) {
            Result.create(ErrorCode.FAILED, "Account or password is illegal.");
        }

        String loginToken = makeToken(jobUserBean);

        CookieUtil.set(response, Constants.USER_LOGIN_KEY, loginToken, ifRemember);
        return Result.create();
    }

    public void logout(HttpServletRequest request, HttpServletResponse response) {
        CookieUtil.remove(request, response, Constants.USER_LOGIN_KEY);
    }

    public JobUserBean checkUserLogin(HttpServletRequest request) throws Exception {
        String userLoginKey = CookieUtil.getValue(request, Constants.USER_LOGIN_KEY);
        //not login
        if (userLoginKey == null) {
            return null;
        }
        JobUserBean loginUser = parseUserLoginKey(userLoginKey);
        if (loginUser != null) {
            JobUserBean jobUserBean = getConfUserBean(loginUser.getUserName());
            if (jobUserBean == null) {
                return null;
            }
            if (Objects.equals(loginUser.getPwd(), jobUserBean.getPwd())) {
                return jobUserBean;
            }
        }
        return null;
    }

    public static List<String> getExcludePatternList() {
        return excludePatternList;
    }

    public static void setExcludePatternList(List<String> excludePatternList) {
        UserLoginService.excludePatternList = excludePatternList;
    }
}
